//***********************************************
//Project Name               :
//File Name                  :Ten_Cor.v
//Author                     :ZJL
//Date of Creation           :
//Functional Description     :本模块使用评价函数Ten_Cor对清晰值进行评价获取当前帧图像的清晰值
// Ten_Cor函数将梯度和相关性结合使用，对每个像素的梯度值用相关性进行加权
// 该模块处理思路：
// 1. 求像素四邻域范围的互相关值，即计算像素的四邻域灰度平均值neigh_value
// neigh_value=1/4*(M1(i-1,j)+M1(i+1,j)+M1(i,j-1)+M1(i,j+1));
// 2. 求像素点与此平均值的互相关
// fcor(i-1,j-1)=(2*M1(i,j)*fneigh)/(M1(i,j)^2+fneigh^2);
// 3. 分别计算X、Y两个方向的互相关值
// Gy(i-1,j-1)=(M1(i+1,j-1)+2*M1(i+1,j)+M1(i+1,j+1))-(M1(i-1,j-1)+2*M1(i-1,j)+M1(i-1,j+1));
// Gx(i-1,j-1)=(M1(i-1,j+1)+2*M1(i,j+1)+M1(i+1,j+1))-(M1(i-1,j-1)+2*M1(i,j-1)+M1(i+1,j-1));
//Revision History           :
// 4. 对梯度平方和与相关性加权累计，求清晰值Ften_cor
// ten_cor=(abs(Gx(i,j))^2+abs(Gy(i,j))^2)*abs(2^16-fcor(i,j));
// Ften_cor=Ften_cor+ten_cor;
//Change Log                 :

// |Line0_0	| Line0_1 | Line0_2 |
// |        |         |         |          
// |Line1_0	| Line1_1 | Line1_2 |
// |        |         |         |         
// |Line2_0	| Line2_1 | Line2_2 |
//***********************************************
module sobel(
//global input interface
    input         wire        [1-1:0]    i_Clk         ,
    input         wire        [1-1:0]    i_Rst_n       ,      
    input         wire        [1-1:0]    i_Frame_rst   ,        
    input         wire        [1-1:0]    i_Data_valid  ,        
    input         wire        [16-1:0]   i_Line0_0     ,    //previous line
    input         wire        [16-1:0]   i_Line0_1     ,        
    input         wire        [16-1:0]   i_Line0_2     ,        
    input         wire        [16-1:0]   i_Line1_0     ,	//current line
    input         wire        [16-1:0]   i_Line1_1     ,        
    input         wire        [16-1:0]   i_Line1_2     ,        
    input         wire        [16-1:0]   i_Line2_0     ,    //next line    
    input         wire        [16-1:0]   i_Line2_1     ,        
    input         wire        [16-1:0]   i_Line2_2     ,     
    output        wire        [1-1:0]    o_Dvld		   ,
    output        wire        [16-1:0]   o_Data                  
);//sobel
reg 	  				data_valid_r1		;
reg 	  				data_valid_r2		;
reg 	  				data_valid_r3		;
reg 	  				data_valid_r4		;
reg     [16-1:0]        line0_0_r1        	;
reg     [16-1:0]        line0_1_r1        	;
reg     [16-1:0]        line0_2_r1        	;
reg     [16-1:0]        line1_0_r1        	;
reg     [16-1:0]        line1_1_r1        	;
reg     [16-1:0]        line1_2_r1        	;
reg     [16-1:0]        line2_0_r1        	;
reg     [16-1:0]        line2_1_r1        	;
reg     [16-1:0]        line2_2_r1        	;
reg		[32-1:0]  		gx_tmp1				;
reg		[32-1:0]  		gy_tmp1				;
reg		[32-1:0]  		gx_tmp2				;
reg		[32-1:0]  		gy_tmp2				;
reg		[32-1:0]  		gx_tmp3				;
reg		[32-1:0]  		gy_tmp3				;
reg		[32-1:0]  		gx_tmp4				;
reg		[32-1:0]  		gy_tmp4				;
reg		[32-1:0]  		gx_tmp5				;
reg		[32-1:0]  		gy_tmp5				;
reg		[32-1:0]  		gx_tmp6				;
reg		[32-1:0]  		gy_tmp6				;
reg		[32-1:0]  		gx_tmp7				;
reg		[32-1:0]  		gy_tmp7				;
reg		[32-1:0]  		gx_tmp8				;
reg		[32-1:0]  		gy_tmp8				;
reg		[32-1:0]  		gx_tmp9				;
reg		[32-1:0]  		gy_tmp9				;
wire	[32-1:0]  		gx					;
wire	[32-1:0]  		gy					;
reg 	[32-1:0]  		post_data			;
wire 	[1-1:0]  		post_dvld			;

reg 	[9:0] 			hcnt					;
reg 	[9:0] 			vcnt					;
reg 		 			post_dvld_r1			;
reg 	[9:0] 			post_hcnt				;
reg 	[9:0] 			post_vcnt				;
wire 	[13:0] 			Average					;

//**********************************************sobel***************************************************
// sobel算子
//计算梯度
// Gy(i-1,j-1)=(M1(i+1,j-1)+2*M1(i+1,j)+M1(i+1,j+1))-(M1(i-1,j-1)+2*M1(i-1,j)+M1(i-1,j+1));
// Gx(i-1,j-1)=(M1(i-1,j+1)+2*M1(i,j+1)+M1(i+1,j+1))-(M1(i-1,j-1)+2*M1(i,j-1)+M1(i+1,j-1));

// 		 |-1 | 0 | 1 |		 | 1 | 2  | 1  |				|Line0_0	| Line0_1 | Line0_2 |
// Sx =  |-2 | 0 | 2 | Sy =  | 0 | 0  | 0  |	M(X,Y) =	|Line1_0	| Line1_1 | Line1_2 |
// 		 |-1 | 0 | 1 |		 |-1 | -2 | -1 |				|Line2_0	| Line2_1 | Line2_2 |

// (line2_2_r1 + 2*line2_1_r1 + line2_0_r1) - ( line0_0_r1 + 2*line0_1_r1 + line0_2_r1 )
// (line0_0_r1 + 2*line1_0_r1 + line2_0_r1) - ( line0_2_r1 + 2*line1_2_r1 + line2_2_r1 )



always @ ( posedge i_Clk ) begin
	if( i_Frame_rst ) begin
		line0_0_r1 <= 'd0;
		line0_1_r1 <= 'd0;
		line0_2_r1 <= 'd0;
		line1_0_r1 <= 'd0;
		line1_1_r1 <= 'd0;
		line1_2_r1 <= 'd0;
		line2_0_r1 <= 'd0;
		line2_1_r1 <= 'd0;
		line2_2_r1 <= 'd0;
	end
	else begin
		line0_0_r1 <= i_Line0_0;
		line0_1_r1 <= i_Line0_1;
		line0_2_r1 <= i_Line0_2;
		line1_0_r1 <= i_Line1_0;
		line1_1_r1 <= i_Line1_1;
		line1_2_r1 <= i_Line1_2;
		line2_0_r1 <= i_Line2_0;
		line2_1_r1 <= i_Line2_1;
		line2_2_r1 <= i_Line2_2;
	end
end


always @ ( posedge i_Clk ) begin
	if( i_Frame_rst ) begin
		gx_tmp1 <=  'd0;
		gx_tmp2 <=  'd0;
		gx_tmp3 <=  'd0;
		gx_tmp4 <=  'd0;

		gy_tmp1 <=  'd0;
		gy_tmp2 <=  'd0;
		gy_tmp3 <=  'd0;
		gy_tmp4 <=  'd0;
	end
	else if( data_valid_r1 )begin
		gx_tmp1 <=  line0_0_r1 + line2_0_r1;
		gx_tmp2 <=  line1_0_r1 + line1_0_r1;
		gx_tmp3 <=  line0_2_r1 + line2_2_r1;
		gx_tmp4 <=  line1_2_r1 + line1_2_r1;

		gy_tmp1 <=  line2_2_r1 + line2_0_r1;
		gy_tmp2 <=  line2_1_r1 + line2_1_r1;
		gy_tmp3 <=  line0_0_r1 + line0_2_r1;
		gy_tmp4 <=  line0_1_r1 + line0_1_r1;
	end
	else begin
		gx_tmp1 <=  0;
		gx_tmp2 <=  0;
		gx_tmp3 <=  0;
		gx_tmp4 <=  0;
		gx_tmp5 <=  0;
		gx_tmp6 <=  0;
		gx_tmp7 <=  0;

		gy_tmp1 <=  0;
		gy_tmp2 <=  0;
		gy_tmp3 <=  0;
		gy_tmp4 <=  0;
		gy_tmp5 <=  0;
		gy_tmp6 <=  0;
		gy_tmp7 <=  0;
	end
end

always @ ( posedge i_Clk ) begin
	if( i_Frame_rst ) begin
		gx_tmp5 <=  'd0;
		gx_tmp6 <=  'd0;
		gx_tmp7 <=  'd0;
		gy_tmp5 <=  'd0;
		gy_tmp6 <=  'd0;
		gy_tmp7 <=  'd0;
	end
	else if( data_valid_r2 )begin
		gx_tmp5 <=  gx_tmp1 + gx_tmp2;
		gx_tmp6 <=  gx_tmp3 + gx_tmp4;
		gx_tmp7 <=  ( gx_tmp5 > gx_tmp6 ) ? (gx_tmp5 - gx_tmp6) : (gx_tmp6 - gx_tmp5);
		gy_tmp5 <=  gy_tmp1 + gy_tmp2;
		gy_tmp6 <=  gy_tmp3 + gy_tmp4;
		gy_tmp7 <=  ( gy_tmp5 > gy_tmp6 ) ? (gy_tmp5 - gy_tmp6) : (gy_tmp6 - gy_tmp5);
	end
	else begin
		gx_tmp5 <=  'd0;
		gx_tmp6 <=  'd0;
		gx_tmp7 <=  'd0;
		gy_tmp5 <=  'd0;
		gy_tmp6 <=  'd0;
		gy_tmp7 <=  'd0;
	end
end	

always @ ( posedge i_Clk ) begin
	if( i_Frame_rst ) begin
		gx_tmp8        <=        'd0;
		gx_tmp9        <=        'd0;

		gy_tmp8        <=        'd0;
		gy_tmp9        <=        'd0;
	end
	else begin
		gx_tmp8        <=        gx_tmp7;
		gx_tmp9        <=        gx_tmp8;

		gy_tmp8        <=        gy_tmp7;
		gy_tmp9        <=        gy_tmp8;
	end
end	
//				|M1(i-1,j-1)	| M1(i-1,j) | M1(i-1,j+1) |
//Gx(i-1,j-1) =	|M1(i,j-1)		| M(X,Y) 	| M1(i,j+1)	  |
//				|M1(i+1,j-1)	| M1(i+1,j) | M1(i+1,j+1) |
//Gx(i-1,j-1)=(M1(i-1,j+1)+2*M1(i,j+1)+M1(i+1,j+1))-(M1(i-1,j-1)+2*M1(i,j-1)+M1(i+1,j-1));
//Gy(i-1,j-1)=(M1(i+1,j-1)+2*M1(i+1,j)+M1(i+1,j+1))-(M1(i-1,j-1)+2*M1(i-1,j)+M1(i-1,j+1));

//gx,gy与focus_region_r5信号对齐
assign gx = gx_tmp7;
assign gy = gy_tmp7;
always @ ( posedge i_Clk ) begin
	if( i_Frame_rst ) begin
		post_data        <=        'd0;
	end
	else if( post_vcnt>=0 && post_vcnt<'d510 )begin
		post_data        <=        gx + gy;
	end
	else begin
		post_data        <=        0;
	end
end	
assign post_dvld = data_valid_r4;


ava_new  u_ava_new (
    .Clk_sys                 ( i_Clk          	),
    .Field_reset_in          ( i_Frame_rst   	),
    .Data_valid_in           ( post_dvld    	),
    .Ifr_data_in             ( post_data	    ),
    .Average                 ( Average          )
);


// assign o_Data = ( post_data>Average) ?  'd255: 0;
assign o_Data = ( post_data>'d139) ?  'd255: 0;
assign o_Dvld = post_dvld;
//**********************************************信号延时***************************************************

always @ ( posedge i_Clk ) begin
	if( i_Frame_rst ) begin
		data_valid_r1 <= 1'd0;
		data_valid_r2 <= 1'd0;
		data_valid_r3 <= 1'd0;
		data_valid_r4 <= 1'd0;
	end
	else begin
		data_valid_r1 <= i_Data_valid;
		data_valid_r2 <= data_valid_r1;
		data_valid_r3 <= data_valid_r2;
		data_valid_r4 <= data_valid_r3;
	end
end
//**********************************************行列计数器***************************************************

// 原始图像行列计数
always @ ( posedge i_Clk ) begin
	if( i_Frame_rst ) begin
		hcnt        <=        'd0;
	end
	else if( i_Data_valid)begin
		hcnt        <=        hcnt + 'd1;
	end
	else begin
		hcnt        <=        'd0;
	end
end
always @ ( posedge i_Clk ) begin
	if( i_Frame_rst ) begin
		vcnt        <=        'd0;
	end
	else if( data_valid_r1 && (~i_Data_valid) )begin
		vcnt        <=        vcnt + 'd1;
	end
	else begin
		vcnt        <=        vcnt;
	end
end
// 输出图像行列计数
always @ ( posedge i_Clk ) begin
	if( i_Frame_rst ) begin
		post_dvld_r1 <= 1'd0;
	end
	else begin
		post_dvld_r1 <= post_dvld;
	end
end
always @ ( posedge i_Clk ) begin
	if( i_Frame_rst ) begin
		post_hcnt        <=        'd0;
	end
	else if( post_dvld)begin
		post_hcnt        <=        post_hcnt + 'd1;
	end
	else begin
		post_hcnt        <=        'd0;
	end
end
always @ ( posedge i_Clk ) begin
	if( i_Frame_rst ) begin
		post_vcnt        <=        'd0;
	end
	else if( post_dvld_r1 && (~post_dvld) )begin
		post_vcnt        <=        post_vcnt + 'd1;
	end
	else begin
		post_vcnt        <=        post_vcnt;
	end
end

// assign o_Data = grade_light[15:0];
endmodule